// function jspang () {
//   let web: String = "Hello World";
//   console.log(web)
// }
// jspang();
// function greeter (person: string) {
//   return "hello," + person;
// }
// let user = "jane user";
// document.body.innerHTML = greeter(user);
// interface Person {
//   firstName: string,
//   lastName: string
// }
// function greeters (person: Person) {
//   return "Hello, " +  person.firstName + ' ' + person.lastName;
// }
// let users = {  firstName: 'jane', lastName: 'user'};
// document.body.innerHTML = greeters(users);
// class Student {
//   fullname: string,
//   constructor (public firstname, public middleinitial, public lastname) {
//     this.fullname = firstname + ' ' + middleinitial + ' ' + lastname;
//   }
// }
// interface Persons {
//   firstname: string,
//   lastname: string
// }
// function gtrrtesss (person: Person) {
//   return "Hello, " + person.firstName + ' ' + person.lastName;
// }
// let userss = new Student('jane', 'm.', 'user filter');
// // document.body.innerHTML = gtrrtesss(userss)
// // 基本静态类型 string number null undefined boolean void symbol
// const xiaojiejie : string [] = ['xx', 'xxx', 'xxxx'];
// class Person {}
// const dajiao : Person = new Person()
// const jiaoxiaojiejie :() => string =()=> { return 'dajiao' }
// // 对象静态类型  数组类型   类类型  函数类型
// // 类型注解
// // 类型推断
// // 函数返回类型
// // function sayHello () : void {
// //   console.log('hello world')
// // }
// function errorFunction () : never {
//   throw new Error()
//   console.log('hello world')
// }
// function forNever () : never {
//   while (true) {}
//   console.log('hello world')
// }
// function add ({one, two} : { one: number, two: number}) {
//   return one + two
// }
// const total = add({one: 1, two: 2})
// function getNumber({one}:{one: number}) {
//   return one
// }
// const one = getNumber({one: 1})
// // 类型数组注解
// const numberArr : number[] = [1,2,3]
// const stringArr : string[] = ['a', 'b', 'c']
// const undefinedArr : undefined[] = [undefined, undefined]
// const arr : (number | string)[] = [1,  'str', 2]
// // type alias 类型别名
// type Lady = { name: string, age: number}
// class Madam {
//   name: string;
//   age: number;
// }
// const xiaojiejiesss : Lady[] = [
//   {name: '1', age: 1},
//   {name: '2', age: 2},
// ]
// const xiaojiejiess : Madam[] = [
//   {name: '1', age: 1},
//   {name: '2', age: 2},
// ]
// const xiaojiejies : {name: string, age: number}[] = [
//   {name: '1', age: 1},
//   {name: '2', age: 2},
// ]
// // 元组  特定类型排列
// const xiaojie1 : (string | number)[] = ['dajiao', 'tea', 28];
// const xiaojie2 : [string, string, number] = ['dajiao', 'tra', 28];
// // csv
// const xiaojie3 : [string, string, number][] = [
//   ['dajiao', 'tra', 28],
//   ['liuying', 'tea', 28],
//   ['curhui', 'tea', 28]
// ]
// // 接口 interface
// interface Girl {
//   name: string;
//   age: number;
//   bust: number;
//   waistline ?: number // ?: 可有可无
// }
// const gril = {
//   name: '大脚',
//   age: 18,
//   bust: 94,
//   waistline: 150
// }
// const screenResume = (gril : Girl ) => {
//   gril.age < 24 && gril.bust >= 90 && console.log(gril.name + '进入面试');
//   gril.age >= 24 || gril.bust < 90 && console.log(gril.name + '你被淘汰');
// }
// const getResume = (gril: Girl) => {
//   console.log(gril.name + '年龄是' + gril.age)
//   console.log(gril.name + '胸围是' + gril.bust)
//   gril.waistline && console.log(gril.name + '腰围是' + gril.waistline)
// }
// screenResume(gril)
// getResume(gril)
// // 初始接口 interface
// interface Girl2 {
//   name: string;
//   age: number;
//   bust: number;
//   waistline ?: number; // ?: 可有可无
//   [propname : string] : any;
//   say(): string;
// }
// // 接口之间继承
// interface Teacher extends Girl2 {
//   teach(): string;
// }
// // 类继承接口
// class XiaoJieJie implements Girl2 {
//   name = '大脚';
//   age = 18;
//   bust = 90;
//   say () {
//     return '欢迎光临， 红浪漫洗浴!!'
//   }
// }
// const gril2 = {
//   name: '大脚',
//   age: 18,
//   bust: 94,
//   waistline: 150,
//   sex: '女',
//   say () {
//     return '欢迎光临， 红浪漫洗浴!'
//   },
//   teach () {
//     return '老师上课!'
//   }
// }
// const screenResume2 = (gril : Girl2 ) => {
//   gril2.age < 24 && gril2.bust >= 90 && console.log(gril2.name + '进入面试');
//   gril2.age >= 24 || gril2.bust < 90 && console.log(gril2.name + '你被淘汰');
// }
// const getResume2 = (gril: Girl2) => {
//   console.log(gril2.name + '年龄是' + gril2.age)
//   console.log(gril2.name + '胸围是' + gril2.bust)
//   gril2.waistline && console.log(gril2.name + '腰围是' + gril2.waistline)
//   gril2.sex && console.log(gril2.name + '腰围是' + gril2.sex)
// }
// const getResume3 = (gril: Teacher) => {
//   console.log(gril2.name + '年龄是' + gril2.age)
//   console.log(gril2.name + '胸围是' + gril2.bust)
//   gril2.waistline && console.log(gril2.name + '腰围是' + gril2.waistline)
//   gril2.sex && console.log(gril2.name + '腰围是' + gril2.sex)
// }
// screenResume2(gril2)
// getResume2(gril2)
// // getResume3(gril2)
// // 类的构造函数
// class Persons {
//   constructor(public name: string) {}
// }
// const person = new Persons('jshupang')
// console.log(person.name);
// // 子类 想要设置构造函数， 就必须super， 、、 父类无特定constructor,子类继承也要super()
// class Teacher extends Person {
//   constructor(public age: number) {
//     super()
//   }
// }
// const teacher = new Teacher(18)
// console.log(teacher.age)
// // 类的getter， setter， static
// // private 和 getter setter的 用处。 _age是私有的，那类的外部就没办法改变，所以这时候可以用setter属性进行改变。
// // 不想new对象，直接使用这个方法，ts提供快捷方式，用static声明的属性和方法，不需要进行声明对象，就可以直接使用。  static
// class GirlStatic {
//   static sayLove () {
//     return ' I Love you'
//   }
// }
// console.log(GirlStatic.sayLove())
// // 抽象类  和 只读属性的使用
// // 只读属性
// class PersonOnlyRead {
//   public readonly _name: string
//   constructor(name: string) {
//     this._name = name
//   }
// }
// const personOnlyRead = new PersonOnlyRead('jshupang')
// console.log(personOnlyRead._name)
// class Person {
//   public name: string;
//   public sayHello() {
//     console.log(this.name + 'say hello')
//   }
// }
// // 以下属于类的外部
// const person = new Person()
// person.name = 'jspang';
// person.sayHello();
// console.log(person.name)
// 抽象类和抽象方法有一个比较深的认识。其实在工作中我们也会把这样的需求用接口来实现。
// 抽象类的使用
// 什么是抽象类那？我给大家举个例子，比如我开了一个红浪漫洗浴中心，里边有服务员，有初级技师，高级技师，每一个岗位我都写成一个类，那代码就是这样的。（注释掉刚才写的代码）
// class Waiter {}
// class BaseTeacher {}
// class seniorTeacher {}
// abstract class Grils{
//   abstract skill()  //因为没有具体的方法，所以我们这里不写括号
// }
// class Waiter extends Grils {
//   skill () {
//     console.log('大爷， 请喝水!')
//   }
// }
// class BaseTeacher extends Grils {
//   skill () {
//     console.log('大爷，来个泰式按摩吧!')
//   }
// }
// class seniorTeacher extends Grils {
//   skill () {
//     console.log('大爷，来个SPA全身按摩吧!')
//   }
// }
// 联合类型和类型保护（类型守护）
// 联合类型和相关的类型保护只是，需要注意的是，只有联合类型存在的情况下，菜需要类型保护。皮特的类型注解，并不需要我们这种特殊操作。
// 所谓联合类型，可以认为一个变量可能有两种或两种以上的类型。用代码举个例子，声明两个接口Waiter(服务员)接口和Teacher(技师)接口，然后在写一个judgeWho(判断是谁)的方法，里边传入一个animal(任意值)，这时候可以能是Waiter,也可能是Teacher。所以我们使用了联合类型，关键符号是|(竖线)。
// // 联合类型
// interface Waiter {
//   anjiao: boolean;
//   say: () => {};
// }
// interface Teacher {
//   anjiao: boolean;
//   skill: () => {};
// }
// function judgeWho(animal: Waiter | Teacher) {}
// 没进行类型保护就会报错
// function judgeWho (animal: Waiter | Teacher) {
//   animal.say();
// }
// 类型保护（类型断言）
// interface Waiter {
//   anjiao: boolean;
//   say: () => {};
// }
// interface Teacher {
//   anjiao: boolean;
//   skill: () => {};
// }
// function judgeWho(animal: Waiter | Teacher) {
//   if (animal.anjiao) {
//     (animal as Teacher).skill();
//   }else {
//     (animal as Waiter).say();
//   }
// }
// // 类型保护 -  in 语法
// // 判断 接口是否有 对应方法
// function judgeWhoTwo (animal: Waiter | Teacher) {
//   if ("skill" in animal) {
//     animal.skill();
//   } else {
//     animal.say();
//   }
// }
// 类型保护户 - typeof 语法
// 如果不进行类型判断，不然就会因为类型不一致导致表达式语法报错
// function add (first: string | number, second: string | number) {
//   return first + second;
// }
// // 正确解决方法
// function add (first: string | number, second: string | number) {
//   if (typeof first === "string" || typeof second === "string") {
//     return `${first}${second}`;
//   }
//   return first + second;
// }
// // 类型保护户 - instanceof 语法     (判断对象类型，  instanceof更合适)
// class NumberObj {
//   count: number;
// }
// // 不做类型保护，这段代码肯定是报错的，  有可能是object并没有count属性值
// // function addObj (first: object | NumberObj, second: object | NumberObj) {
// //   return first.count + second.count;
// // }
// // 报错不要紧，直接使用instanceof语法进行判断一下，就可以解决问题 || instanceof  只能用在类上
// function addObj (first: object | NumberObj, second: object | NumberObj) {
//   if (first instanceof NumberObj && second instanceof NumberObj) {
//     return first.count + second.count;
//   }
//   return 0;
// }
// 枚举类型 enum
// // 初级程序员写法：
// function getServe1 (status: number) {
//   if (status === 0) {
//     return "message";
//   } else if (status === 1) {
//     return "SPA";
//   } else if (status === 2) {
//     return "dabaojian";
//   }
// }
// const result = getServe1(0);
// console.log(`我要去${result}`)
// // 中级程序员写法:
// const Status = {
//   MESSAGE: 0,
//   SPA: 1,
//   DABAOJIAN: 2
// }
// function getServe2 (status: any) {
//   if (status === Status.MESSAGE) {
//     return "message";
//   } else if (status === Status.SPA) {
//     return "spa";
//   } else if (status === Status.DABAOJIAN) {
//     return "dabaojian";
//   }
// }
// const result2 = getServe2(Status.SPA);
// console.log(`我要去${result2}`)
// 高级程序员写法：
var Staus;
(function (Staus) {
    Staus[Staus["MESSAGE"] = 0] = "MESSAGE";
    Staus[Staus["SPA"] = 1] = "SPA";
    Staus[Staus["DABAOJIAN"] = 2] = "DABAOJIAN";
})(Staus || (Staus = {}));
function getServe3(status) {
    if (status === Status.MESSAGE) {
        return "message";
    }
    else if (status === Status.SPA) {
        return "spa";
    }
    else if (status === Status.DABAOJIAN) {
        return "dabaojian";
    }
}
// 枚举类型的对应值
var result3 = getServe3(Status.SPA);
var result4 = getServe3(1);
console.log("\u6211\u8981\u53BB" + result3);
console.log("\u6211\u8981\u53BB" + result4);
// 枚举通过下标反查
console.log(Status.MESSAGE, Status[1]);
